package net.qiqb.spring.autoconfig;

import net.qiqb.core.domain.event.DomainEventLogPersistence;
import net.qiqb.core.domain.event.DomainEventPersistence;
import net.qiqb.core.domain.event.receiver.*;
import net.qiqb.core.domain.event.sender.DefaultDomainEventSender;
import net.qiqb.core.domain.event.sender.DomainEventSender;
import net.qiqb.dao.mybatis.plus.event.*;
import net.qiqb.spring.domain.event.SpringDomainEventMulticaster;
import net.qiqb.spring.tx.SpringTransaction;
import org.apache.dubbo.config.spring.context.DubboSpringInitContext;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ApplicationEventMulticaster;

import static org.springframework.context.support.AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME;

/**
 * mybatis plus 实现领域事件数据库持久化
 */
@Configuration
@MapperScan("net.qiqb.dao.mybatis.plus.event")
public class DomainEventConfiguration {

    @Bean
    public DomainEventDao domainEventDao() {
        return new DomainEventDaoImpl();
    }

    @Bean
    public DomainEventLogDao domainEventLogDao() {
        return new DomainEventLogDaoImpl();
    }


    @Bean
    public DomainEventPersistence domainEventPersistence() {
        return new DomainEventPersistenceImpl();
    }

    @Bean
    public DomainEventLogPersistence domainEventLogPersistence() {
        return new DomainEventLogPersistenceImpl();
    }


    /**
     * spring 事务
     *
     * @return
     */
    @Bean
    public SpringTransaction transaction() {
        return new SpringTransaction();
    }


    /**
     * @param beanFactory
     * @return
     */
    @Bean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)
    public ApplicationEventMulticaster applicationEventMulticaster(ConfigurableListableBeanFactory beanFactory, ApplicationContext applicationContext) {
        return new SpringDomainEventMulticaster(beanFactory, applicationContext);
    }


    @ConditionalOnMissingBean(DubboSpringInitContext.class)
    @Bean
    public DomainEventReceiver localDomainEventReceiver(SpringDomainEventMulticaster springDomainEventMulticaster) {
        return new LocalDomainEventReceiver(springDomainEventMulticaster);
    }

    @ConditionalOnBean(DubboSpringInitContext.class)
    @Configuration
    public static class DubboDomainEventConfiguration {

        @Bean
        public DomainEventModuleService domainEventModuleService() {
            return new DomainEventModuleServiceImpl();
        }

        @Bean
        public DomainEventReceiver dubboDomainEventReceiver() {
            return new DubboDomainEventReceiver();
        }


    }


    @Bean
    public DomainEventSender defaultDomainEventSender(DomainEventPersistence persistence, DomainEventReceiver domainEventReceiver) {
        return new DefaultDomainEventSender(persistence, domainEventReceiver);
    }
}
